#pragma once

#include "rtda/frame.h"
#include "rtda/heap/object.h"
#include "rtda/heap/slots.h"
#include "native/registry.h"
#include <cstdint>
#include <map>
#include <vector>
#include <memory>

namespace jvm {
    namespace misc {

        class Unsafe {
        public:
            static void registerNatives();

            // Memory operations
            static void arrayBaseOffset(std::shared_ptr<rtda::Frame> frame);
            static void arrayIndexScale(std::shared_ptr<rtda::Frame> frame);
            static void addressSize(std::shared_ptr<rtda::Frame> frame);
            static void objectFieldOffset(std::shared_ptr<rtda::Frame> frame);
            static void compareAndSwapObject(std::shared_ptr<rtda::Frame> frame);
            static void getInt(std::shared_ptr<rtda::Frame> frame);
            static void compareAndSwapInt(std::shared_ptr<rtda::Frame> frame);
            static void getObject(std::shared_ptr<rtda::Frame> frame);
            static void compareAndSwapLong(std::shared_ptr<rtda::Frame> frame);

            // Memory management
            static int64_t allocateMemory(int64_t bytes);
            static int64_t reallocateMemory(int64_t address, int64_t bytes);
            static void freeMemory(int64_t address);
            static void putLong(int64_t address, int64_t value);
            static int8_t getByte(int64_t address);

        private:
            static bool casObject(std::shared_ptr<heap::Object> obj, heap::Slots& fields, int64_t offset,
                std::shared_ptr<heap::Object> expected, std::shared_ptr<heap::Object> newVal);
            static bool casArray(std::vector<std::shared_ptr<heap::Object>>& objs, int64_t offset,
                std::shared_ptr<heap::Object> expected, std::shared_ptr<heap::Object> newVal);
            static std::vector<uint8_t>& memoryAt(int64_t address);

            static std::map<int64_t, std::vector<uint8_t>> g_allocatedMemory;
            static int64_t g_nextAddress;
        };

    } // namespace misc
} // namespace jvm
